package com.ding.dailyup.controller;

import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.function.Function;
import java.util.stream.Collectors;

import com.ding.dailyup.entity.request.StrategyApplicationReq;
import com.ding.dailyup.exception.BOException;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.ding.dailyup.annotation.LoginUser;
import com.ding.dailyup.emum.StrategyStatusEnum;
import com.ding.dailyup.entity.JsonResult;
import com.ding.dailyup.entity.request.CollectStrategyReq;
import com.ding.dailyup.entity.response.StockStrategyResp;
import com.ding.dailyup.entity.response.StrategyCategoryResp;
import com.ding.dailyup.entity.response.StrategyIndexResp;
import com.ding.dailyup.entity.response.StrategyWithCategoryResp;
import com.ding.dailyup.model.StockStrategy;
import com.ding.dailyup.model.StrategyCategory;
import com.ding.dailyup.model.UserBuyStrategy;
import com.ding.dailyup.model.UserCollectStrategy;
import com.ding.dailyup.service.StockStrategyService;
import com.ding.dailyup.service.StrategyCategoryService;
import com.ding.dailyup.service.UserCollectStrategyService;
import com.ding.dailyup.service.UserService;
import com.ding.dailyup.util.UserTokenUtil;
import com.google.common.collect.Lists;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;

@RestController
@RequestMapping("/strategy")
@Api(tags = "策略模块")
public class StrategyController {
	@Autowired
	private StockStrategyService stockStrategyService;
	@Autowired
	private UserCollectStrategyService userCollectStrategyService;
	@Autowired
	private StrategyCategoryService strategyCategoryService;
	@Autowired
	private UserService userService;

	@ApiOperation(value = "策略列表")
	@GetMapping(value = "/list")
	public JsonResult<List<StockStrategyResp>> strategyList(
			@LoginUser Long userId) {

		List<StockStrategyResp> strategyList = stockStrategyService
				.listStrategies().parallelStream()
				.sorted(Comparator.comparing(StockStrategy::getSortKey)
						.thenComparing(StockStrategy::getId))
				.map(stockStrategy -> {
					StockStrategyResp resp = new StockStrategyResp();
					BeanUtil.copyProperties(stockStrategy, resp);
					return resp;
				}).collect(Collectors.toList());

		List<Long> buyStrategy = userService.getUserBuyStrategy(userId).stream()
				.map(UserBuyStrategy::getStrategyId)
				.collect(Collectors.toList());

		strategyList.forEach(item -> {
			Long id = item.getId();
			String desc = StrategyStatusEnum.getDesc(item.getStatus());
			if (StrUtil.isNotEmpty(desc) && item
					.getStatus() != StrategyStatusEnum.DEFAULT.status()) {
				item.setStrategyName(
						item.getStrategyName() + " （" + desc + "）");
			}
			if (buyStrategy.contains(id)) {
				item.setStatus(StrategyStatusEnum.FREE.status());
			}
		});
		return JsonResult.succResult(strategyList);
	}

	@ApiOperation(value = "策略列表")
	@GetMapping(value = "/list/v2")
	public JsonResult<List<StockStrategyResp>> strategyListV2(
			@LoginUser Long userId) {
		return JsonResult.succResult(this.getUserCollectStrategy(userId));
	}

	@ApiOperation(value = "用户收藏策略列表")
	@GetMapping(value = "/collect/list")
	public JsonResult<List<UserCollectStrategy>> listCollectStrategy(
			@LoginUser Long userId) {
		return JsonResult.succResult(
				userCollectStrategyService.listUserCollectStrategies(userId));
	}

	@ApiOperation(value = "收藏策略")
	@GetMapping(value = "/collect")
	public JsonResult collectStrategy(
			@RequestParam(value = "strategyId") Long strategyId,
			@RequestParam(value = "strategyName") String strategyName,
			@LoginUser Long userId) {
		userCollectStrategyService.collectStrategy(strategyId, strategyName,
				userId);
		return JsonResult.succResult();
	}

	@ApiOperation(value = "收藏策略")
	@PostMapping(value = "/collect")
	public JsonResult collectStrategy(
			@RequestParam(value = "strategyId") @ApiParam(value = "逗号隔开, strategyIds ") List<CollectStrategyReq> collectStockReqs,
			@LoginUser Long userId) {
		UserTokenUtil.needLogin(userId);
		collectStockReqs.forEach(item -> {
			userCollectStrategyService.collectStrategy(item.getStrategyId(),
					item.getStrategyName(), userId);
		});
		return JsonResult.succResult();
	}

	@ApiOperation(value = "取消收藏策略")
	@GetMapping(value = "/cancel/collect")
	public JsonResult cancelCollectStrategy(
			@RequestParam(value = "strategyId") Long strategyId,
			@LoginUser Long userId) {
		userCollectStrategyService.cancelCollectStrategy(strategyId, userId);
		return JsonResult.succResult();
	}

	@ApiOperation(value = "策略详情")
	@GetMapping(value = "/details")
	public JsonResult<List<StockStrategyResp>> strategyDetail(
			@RequestParam(value = "strategyIds") String strategyIds) {
		List<StockStrategyResp> collect = Lists.newArrayList();
		if (StringUtils.isNotEmpty(strategyIds)) {
			collect = Arrays.stream(strategyIds.split(",")).map(strId -> {
				long l = Long.parseLong(strId);
				StockStrategy byId = stockStrategyService.findById(l);
				StockStrategyResp stockStrategyResp = new StockStrategyResp();
				BeanUtils.copyProperties(byId, stockStrategyResp);
				return stockStrategyResp;
			}).collect(Collectors.toList());
		}
		return JsonResult.succResult(collect);
	}

	@ApiOperation(value = "策略功能提交")
	@PostMapping(value = "/application")
	public JsonResult strategyApplication(
			@RequestBody StrategyApplicationReq req, @LoginUser Long userId) {
		UserTokenUtil.needLogin(userId);
		String strategyName = req.getStrategyName();
		String strategyContext = req.getStrategyContext();
		String remark = req.getRemark();
		double reward = req.getReward();
		int runType = req.getRunType();
		String wxId = req.getWxId();
		if (StrUtil.isEmpty(strategyContext)
				|| strategyContext.length() > 500) {
			throw new BOException("请填写策略详情");
		}
		if (StrUtil.isEmpty(wxId) || wxId.length() > 200) {
			throw new BOException("请填写微信号");
		}
		if (strategyName.length() > 50) {
			throw new BOException("请规范填写策略名称");
		}
		stockStrategyService.saveStrategyApplication(strategyName,
				strategyContext, remark, reward, runType, userId, wxId);
		return JsonResult.succResult();
	}

	/**
	 * 私人定制的策略流程:<br/>
	 * 1. stockStrategy添加, 类型是私人订制 <br/>
	 * 2. 用户收藏user_collect_strategy <br/>
	 * 3. 用户购买 user_buy_strategy<br/>
	 * 
	 * 4. user_info strategyNumber ++
	 * 
	 * @param userId
	 * @return
	 */
	@ApiOperation(value = "策略&分类, 策略页面首页内容")
	@GetMapping(value = "/index")
	public JsonResult getStrategyCategory(@LoginUser Long userId) {
		// 用户收藏列表
		List<StockStrategyResp> userCollectStrategyList = this
				.getUserCollectStrategy(userId);
		// 用户收藏的策略ids
		List<Long> collectStrategyIds = userCollectStrategyList.stream()
				.map(StockStrategyResp::getId).collect(Collectors.toList());

		JSONArray items = new JSONArray();
		JSONArray collectStrategyInfo = new JSONArray();
		// 展示所用策略分类
		List<StrategyCategory> categories = strategyCategoryService
				.listStrategyCategories();
		List<StrategyWithCategoryResp> allStrategies = Lists.newArrayList();
		for (StrategyCategory category : categories) {

			JSONObject item = new JSONObject();
			item.put("text", category.getCategoryName());
			int collectCount = 0;
			StrategyWithCategoryResp strategyWithCategoryResp = new StrategyWithCategoryResp();
			StrategyCategoryResp strategyCategoryResp = new StrategyCategoryResp();
			BeanUtils.copyProperties(category, strategyCategoryResp);
			JSONArray child = new JSONArray();

			List<StockStrategy> strategies = Lists.newArrayList();
			// 如果是私人定制的策略
			if (category.getCategoryId() == 6) {
				strategies = userService.getUserBuyStrategy(userId).stream()
						.map(UserBuyStrategy::getStrategyId)
						.map(strategyId -> stockStrategyService
								.findById(strategyId))
						.collect(Collectors.toList());

			} else {
				strategies = stockStrategyService
						.findByCategoryId(category.getCategoryId());
			}
			for (StockStrategy stockStrategy : strategies) {
				JSONObject strategy = new JSONObject();
				strategy.put("id", stockStrategy.getId());
				strategy.put("text", stockStrategy.getStrategyName());
				if (collectStrategyIds.contains(stockStrategy.getId())
						|| category.getCategoryId() == 6) {
					collectStrategyInfo.add(strategy);
					collectCount++;
				}
				child.add(strategy);
			}
			if (collectCount > 0) {
				item.put("badge", collectCount);
			}
			item.put("children", child);
			items.add(item);
			List<StockStrategyResp> stockStrategiesReps = stockStrategyService
					.findByCategoryId(category.getCategoryId()).stream()
					.map(stockStrategy -> {
						StockStrategyResp stockStrategyResp = new StockStrategyResp();
						BeanUtils.copyProperties(stockStrategy,
								stockStrategyResp);
						// 处理收藏状态
						stockStrategyResp.setCollected(collectStrategyIds
								.contains(stockStrategyResp.getId()));
						return stockStrategyResp;
					}).collect(Collectors.toList());
			strategyWithCategoryResp
					.setStockStrategyRespList(stockStrategiesReps);
			strategyWithCategoryResp.setStrategyCategory(strategyCategoryResp);
			allStrategies.add(strategyWithCategoryResp);
		}
		// 最后赋值
		StrategyIndexResp strategyIndexResp = new StrategyIndexResp();
		strategyIndexResp.setStrategyWithCategoryResps(allStrategies);
		strategyIndexResp.setUserCollectStrategy(userCollectStrategyList);

		JSONObject rs = new JSONObject();
		rs.put("items", items);
		rs.put("activeId", collectStrategyIds);
		rs.put("collectStrategyInfo", collectStrategyInfo);
		return JsonResult.succResult(rs);
	}

	private List<StockStrategyResp> getUserCollectStrategy(
			@LoginUser Long userId) {
		List<StockStrategyResp> userCollectStrategyList;
		if (UserTokenUtil.isLogin(userId)) {
			List<UserCollectStrategy> userCollectStrategies = userCollectStrategyService
					.listUserCollectStrategies(userId);

			userCollectStrategyList = userCollectStrategies.stream()
					.map(userCollectStrategy -> {
						StockStrategyResp stockStrategyResp = new StockStrategyResp();
						BeanUtil.copyProperties(userCollectStrategy,
								stockStrategyResp);
						stockStrategyResp
								.setId(userCollectStrategy.getStrategyId());
						return stockStrategyResp;
					}).collect(Collectors.toList());
		} else {
			List<StockStrategy> defaultStrategies = stockStrategyService
					.listDefaultStrategies();
			userCollectStrategyList = defaultStrategies.stream()
					.map(stockStrategy -> {
						StockStrategyResp stockStrategyResp = new StockStrategyResp();
						BeanUtil.copyProperties(stockStrategy,
								stockStrategyResp);
						return stockStrategyResp;
					}).collect(Collectors.toList());
		}
		return userCollectStrategyList;
	}
}
